package com.example.PacMan;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

public class MyPanel extends JPanel implements KeyListener, Runnable {
    //define player
    YellowMan ym = null;
    Vector<Ghost> ghosts = new Vector<>();
    int ghostNums = 3;

    Vector<Point> points = new Vector<>();
    int pointNums = 3;

    Wall wall = null;


    Vector<Node01> node01s = new Vector<>();
    Vector<Node02> node02s = new Vector<>();


    public MyPanel(String key) {
        //node01s = Recorder.getNode01AllGhost();
        node02s = Recorder.getNode02AllPoint();

        Recorder.setGhosts(ghosts);
        Recorder.setPoints(points);

        ym = new YellowMan(500, 300);
        ym.setSpeed(10);

        wall = new Wall(400, 0);


        for (int i = 0; i < ghostNums; i++) {
            Ghost ghost = new Ghost(100 * (i + 1), 0);
            ghosts.add(ghost);
            ghost.setDirect(2);
            new Thread(ghost).start();
            ghost.setSpeed(1);
        }

        for (int i = 0; i < pointNums; i++) {
            Point point = new Point(200, 100 * (i + 1));
            points.add(point);
        }
    }

    public void judgeIsCrash() {
        //there use different way to write judge method
        //to judge if ghost touch ym
        ghosts.forEach(e -> {
            int r1 = 15;
            int r2 = 15;
            int centerX1 = ym.getX() + r1;
            int centerY1 = ym.getY() + r1;

            int centerX2 = e.getX() + r2;
            int centerY2 = e.getY() + r2;
            double length = Math.sqrt(Math.pow(centerX1 - centerX2, 2)
                    + Math.pow(centerY1 - centerY2, 2));
            if (length < (r1 + r2)) {
                ym.setLive(false);
            }
        });
        //to judge if ym touch points
        for (Point point : points) {
            int r1 = 30;
            int r2 = 10;
            int centerX1 = ym.getX() + r1;
            int centerY1 = ym.getY() + r1;

            int centerX2 = point.getX() + r2;
            int centerY2 = point.getY() + r2;
            double length = Math.sqrt(Math.pow(centerX1 - centerX2, 2)
                    + Math.pow(centerY1 - centerY2, 2));
            if (length < (r1 + r2) && point.isLive) {
                point.setLive(false);
                //to record point that player touch the point
                Recorder.addAllPointNum();
            }
        }

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0, 0, 1000, 750);
        showInfo(g);
        judgeIsCrash();
        if (ym.isLive) {
            drawObject(ym.getX(), ym.getY(), g, ym.getDirect(), 0);
        }

        for (int i = 0; i < ghosts.size(); i++) {
            Ghost ghost = ghosts.get(i);
            drawObject(ghost.getX(), ghost.getY(), g, ghost.getDirect(), 1);
        }

        for (int i = 0; i < points.size(); i++) {
            Point point = points.get(i);
            if (point.isLive) {
                drawPoint(point.getX(), point.getY(), g);
            }

        }
        drawWall(wall.getX(), wall.getY(), g);


    }

    public void showInfo(Graphics g) {
        g.setColor(Color.black);
        Font font = new Font("宋体", Font.BOLD, 20);
        g.setFont(font);

        g.drawString("Your points is: ", 1020, 30);
        drawPoint(1020, 50, g);

        g.setColor(Color.black);
        g.drawString(Recorder.getAllPointNum() + "", 1080, 65);
    }

    //0 is player, 1 is ghost
    public void drawObject(int x, int y, Graphics g, int direct, int type) {

        switch (type) {
            case 0:
                g.setColor(Color.yellow);
                break;
            case 1:
                g.setColor(Color.cyan);
                break;
        }
        switch (direct) {
            case 0:
                g.fillOval(x, y, 30, 30);
                break;
            case 1:
                g.fillOval(x, y, 30, 30);
                break;
            case 2:
                g.fillOval(x, y, 30, 30);
                break;
            case 3:
                g.fillOval(x, y, 30, 30);
                break;
        }

    }

    public void drawPoint(int x, int y, Graphics g) {
        g.setColor(Color.ORANGE);
        g.fillOval(x, y, 10, 10);
    }

    public void drawWall(int x, int y, Graphics g) {
        g.setColor(Color.RED);
        g.fill3DRect(x, y, 5, 650, false);
    }

    public boolean touchTop() {
        //判断是否碰到上方墙壁
        return ym.getX() + 30 >= wall.getX() && ym.getX() <= wall.getX() + 5 && ym.getY() <= 650;
    }

    public boolean touchleft() {
        if (ym.getX() + 30 >= wall.getX() && ym.getX() <= wall.getX() + 5 && ym.getY() <= 650) {
            return true;
        }
        return false;
    }

    public boolean touchRight() {
        if (ym.getX() <= (wall.getX() + 5) && ym.getX() >= wall.getX() && ym.getY() <= 650) {
            return true;
        }
        return false;
    }

    public boolean touchWall() {
        if (ym.getX() >= wall.getX() && ym.getX() <= wall.getX() + 5
                && ym.getY() >= wall.getY() && ym.getY() <= wall.getY() + 650) {
            return true;
        }
        return false;
    }


    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_W) {

            if (!touchTop() && ym.getY() > 0) {
                ym.moveUp();
            }


        } else if (!touchleft() && e.getKeyCode() == KeyEvent.VK_D) {
            if (ym.getX() + 30 < 1000) {
                ym.moveRight();
            }
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            if (ym.getY() + 30 < 750) {
                ym.moveDown();
            }
        } else if (!touchRight() && e.getKeyCode() == KeyEvent.VK_A) {
            if (ym.getX() + 30 < 1000) {
                ym.moveLeft();
            }
        }

        //must to use repaint, if not, it will cannot to move
        this.repaint();
    }


    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            this.repaint();
        }
    }
}
